/**
 *  Serponix is an arcade game in focus to multiplayer based on the classic game Snake.
 *  Copyright (C) 2010 - 2011  Daniel Vala
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License,
 *  or  any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.

 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 *  If you have any question do not hesitate to contact author
 *  on e-mail address: danielvala42@gmail.com
 */
package com.serponix.game.score;

import com.serponix.game.Consts;
import com.serponix.settings.GameSettings;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.LinkedList;
import java.util.List;
import javax.swing.JOptionPane;

/**
 * High-skore obsahuje 5 nejlepších výsledků.
 * Umí se uložit do souboru, načíst se ze souboru,
 * řadit skóre do TOP 5 a přehledně se zobrazit.
 *
 * @author Daniel Vala
 */
public class HighSkore {

	private static final int MAXIMALNI_POCET_ZAZNAMU = 5;
	private static final String JMENO_SOUBORU = "high-skore.ser";
	private static List<ZaznamSkore> skoreList;

	/**
	 * Zapíše zadané skóre na jeho místo v TOP 5.
	 *
	 * @param skore Počet bodů skóre.
	 */
	public static void zapisSkore(int skore) {
		// nulové či záporné skóre se nikdy nikam nezapíše
		if (skore <= 0) {
			return;
		}

		// zobrazení dialogového okna pro zápis nicku
		String nick = JOptionPane.showInputDialog("Zadejejte své jméno", GameSettings.getInstance().getNameOfGivenPlayer(0));

		// pokud neexistuje některý z potřebných adresářů nebo soubor high-skore.ser,
		// vytvoří se a do souboru se doplní do něj prázdné záznamy
		new File(Consts.GAME_DIR).mkdirs();
		if (!new File(Consts.GAME_DIR + JMENO_SOUBORU).exists()) {
			vytvorPrazdneSkore();
		} else {
			skoreList = nactiSkore();
		}
		zaradSkore(skore, nick);
		ulozSkore();

		zapisSkoreNaWeb(nick, skore);
	}

	/**
	 * Zobrazí 5 nejlepších výsledků se jmény autorů.
	 */
	public static void zobrazSkore() {
		new File(Consts.GAME_DIR).mkdirs();
		if (!new File(Consts.GAME_DIR + JMENO_SOUBORU).exists()) {
			vytvorPrazdneSkore();
			ulozSkore();
		} else {
			skoreList = nactiSkore();
		}
		JOptionPane.showMessageDialog(null, String.format("%-15s%-10s\n %-15s%-10s\n %-15s%-10s\n %-15s%-10s\n %-15s%-10s\n %-15s%-10s\n", " nick", "skore", skoreList.get(0).getNick(), skoreList.get(0).getSkore(), skoreList.get(1).getNick(), skoreList.get(1).getSkore(), skoreList.get(2).getNick(), skoreList.get(2).getSkore(), skoreList.get(3).getNick(), skoreList.get(3).getSkore(), skoreList.get(4).getNick(), skoreList.get(4).getSkore()), "TOP 5", JOptionPane.INFORMATION_MESSAGE);
	}

	/**
	 * Vytvoří prázdné skóre bez jmen a záznamů o počtu bodů.
	 */
	private static void vytvorPrazdneSkore() {
		// vytvoření seznamu pro uložení jednotlivých pozic skore
		skoreList = new LinkedList<ZaznamSkore>();
		for (int i = 0; i < MAXIMALNI_POCET_ZAZNAMU; i++) {
			skoreList.add(i, new ZaznamSkore("------", 0));
		}
		JOptionPane.showMessageDialog(null, "Byl vytvořen nový soubor " + JMENO_SOUBORU);
	}

	/**
	 * Zařadí zadané skóre do TOP 5.
	 *
	 * @param skore Skóre, které má být zařazeno.
	 */
	private static void zaradSkore(int skore, String nick) {
		// pokud je dosažené skóre nižžší, než na poslední pozici, nezapíše se.
		if (skoreList.get(4).getSkore() >= skore) {
			return;
		}
		for (int i = 0; i < skoreList.size(); i++) {
			// jestliže je dosažené skóre větší, než na aktuálně prohledávaném místě, přidá se na tuto pozici a metoda se ukončí
			if (skore > skoreList.get(i).getSkore()) {
				skoreList.add(i, new ZaznamSkore(nick, skore));
				return;
			}
		}
		// přidá dosažené skóre na poslední místo
		skoreList.add(skoreList.size(), new ZaznamSkore(nick, skore));
	}

	@SuppressWarnings("unchecked")
	private static List<ZaznamSkore> nactiSkore() {
		ObjectInputStream input = null;
		List<ZaznamSkore> list = new LinkedList<ZaznamSkore>();
		try {
			input = new ObjectInputStream(new FileInputStream(Consts.GAME_DIR + JMENO_SOUBORU));
			list = (List<ZaznamSkore>) input.readObject();
		} catch (FileNotFoundException ex) {
			JOptionPane.showMessageDialog(null, "Soubor mapy nebyl nalezen.", "Chyba", JOptionPane.ERROR_MESSAGE);
		} catch (ClassCastException ex) {
			JOptionPane.showMessageDialog(null, "Chyba čtení souboru. Soubor high-skore nenbyl vytvořen v této hře. Prosím smažte jej." +
					"\n Cesta k souboru: " + Consts.GAME_DIR + JMENO_SOUBORU, "Chyba", JOptionPane.ERROR_MESSAGE);
			System.exit(1);
		} catch (IOException ex) {
			JOptionPane.showMessageDialog(null, "Chyba čtení souboru. Soubor high-skore nebyl vytvořen v této hře. Prosím smažte jej." +
					"\n Cesta k souboru: " + Consts.GAME_DIR + JMENO_SOUBORU, "Chyba", JOptionPane.ERROR_MESSAGE);
			System.exit(1);
		} catch (ClassNotFoundException ex) {
			JOptionPane.showMessageDialog(null, "Chyba při čtení souboru high-skore.", "Chyba", JOptionPane.ERROR_MESSAGE);
		} finally {
			try {
				input.close();
			} catch (IOException ex) {
				JOptionPane.showMessageDialog(null, "Chyba při zavírání souboru high-skore.", "Chyba", JOptionPane.ERROR_MESSAGE);
			}
		}
		return list;
	}

	private static void ulozSkore() {
		ObjectOutputStream output = null;
		try {
			output = new ObjectOutputStream(new FileOutputStream(new File(Consts.GAME_DIR + JMENO_SOUBORU)));
			output.writeObject(skoreList);
		} catch (FileNotFoundException ex) {
			JOptionPane.showMessageDialog(null, "Ověřte, že máte do oprávnění do složky " + Consts.GAME_DIR, "Chyba", JOptionPane.ERROR_MESSAGE);
		} catch (IOException ex) {
			JOptionPane.showMessageDialog(null, "Ověřte, že máte do oprávnění do složky " + Consts.GAME_DIR, "Chyba", JOptionPane.ERROR_MESSAGE);
		} finally {
			try {
				if (output != null) {
					output.close();
				}
			} catch (IOException ex) {
				JOptionPane.showMessageDialog(null, "Chyba při zavírání souboru high-skore.", "Chyba", JOptionPane.ERROR_MESSAGE);
			}
		}
	}

	private static void zapisSkoreNaWeb(String nick, int skore) {
		URL url = null;
		try {
			url = new URL("http://www.serponix.com/zapisVysledek?afgipkpokograj=" + nick + "&kgrajpogajfdae=" + skore);
		} catch (MalformedURLException ex) {
			System.err.println("chyba URL");
		}
		try {
			url.getContent();
		} catch (IOException ex) {
			System.err.println("IO chyba");
		}
	}
}
